#!/usr/bin/env python3 
# -*- coding:utf-8 -*-

from collections import namedtuple, deque, defaultdict, OrderedDict, Counter

# collections 是 python 内建的一个集合模块,提供了许多有用的集合类
# namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
print(p.x)

# namedtuple 是一个函数,它用来创建一个自定义的 tuple 对象,并且规定了 tuple 元素的个数,
# 并可以用属性而不是索引来引用 tuple 的某个元素, 这样一来,我们用 namedtuple 可以很方便定义一种数据类型
# 它具备 tuple 的不变性,又可以根据属性来引用,使用十分方便

print(isinstance(p, Point))
print(isinstance(p, tuple))

# 类似的,如果要用坐标和半径表示一个圆,也可以用 namedtuple 来定义
Circle = namedtuple('Circle', ['x', 'y', 'r'])

# deque
# 使用 list 存储数据时候,按索引访问元素很快,但是插入和删除元素就很慢了,因为 list 是线性存储,数据量很大的时候,插入和删除效率很低
# deque 是为了高效实现插入和删除操作的双向列表,适用于队列和栈

q = deque(['a', 'b', 'c'])
q.append('x')
print(q)  # deque(['a', 'b', 'c', 'x'])
q.appendleft('f')
print(q)  # deque(['f', 'a', 'b', 'c', 'x'])

# deque除了实现list的append()和pop()外，还支持appendleft()和popleft()，这样就可以非常高效地往头部添加或删除元素

# defaultdict
# 使用 dict 时,如果引用的 key 不存在,就会抛出 KeyError,如果希望 key 不存在时,返回一个默认值,就可以使用 defaultdict
dd = defaultdict(lambda: "N/A")
dd['key1'] = 'abc'
print(dd['key1'])  # abc
print(dd['key2'])  # N/A
# 注意默认值是调用函数返回的,而函数在创建 defaultdict 对象时传入
# 除了 key 不存在的时候返回默认值, defaultdict 的其他行为和 dict 完全一样

# OrderedDict
# dict中 key 是无序的,要保持 key 的顺序,可以用 OrderedDict
d = dict([('a', 1), ('b', 2), ('c', 3)])
print(d)  # {'a': 1, 'b': 2, 'c': 3}

od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])

print(od)  # OrderedDict([('a', 1), ('b', 2), ('c', 3)])
# OrderedDict 照插入的顺序排列，不是Key本身排序
od = OrderedDict()
od['z'] = 1
od['y'] = 2
od['x'] = 3
print(list(od.keys()))  # OrderedDict


# OrderedDict 可以实现一个 FIFO 先进先出的 dict, 当容量超出限制时候,先删除最早添加的 key
class LastUpdatedOrderedDict(OrderedDict):

    def __init__(self, capacity):
        super(LastUpdatedOrderedDict, self).__init__()
        self._capacity = capacity

    def __setitem__(self, key, value):
        containsKey = 1 if key in self else 0
        if len(self) - containsKey >= self._capacity:
            last = self.popitem(last=False)
            print('remove:', last)
        if containsKey:
            del self[key]
            print('set:', (key, value))
        else:
            print('add:', (key, value))
        OrderedDict.__setitem__(self, key, value)


# counter : Counter 是一个简单的计数器
c = Counter()
for ch in "playcomputergame":
    c[ch] = c[ch] + 1

print(c)
# Counter实际上也是dict的一个子类
